package com.gitee.jiaojinxin.oauth2.auth.config;

import com.gitee.jiaojinxin.oauth2.auth.bo.MyClientBOImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.builders.JdbcClientDetailsServiceBuilder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;

import javax.sql.DataSource;
import java.util.Arrays;

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

//    @Autowired
//    private DataSource dataSource;

//    @Autowired
//    private PasswordEncoder passwordEncoder;

    @Autowired
    private RedisConnectionFactory redisConnectionFactory;

    @Autowired
    private MyClientBOImpl clientDetailsService;

//    @Autowired
//    private MyTokenEnhancer myTokenEnhancer;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 1：内存中
//        clients.inMemory()
//                .withClient("client1")
//                .secret(passwordEncoder.encode("secret1"))
//                .authorizedGrantTypes("authorization_code")
//                .redirectUris("http://localhost:8004/login")
//                .resourceIds("resource1")
//                .scopes("read", "write")
//                .autoApprove(true)
//                .and()
//                .withClient("client2")
//                .secret(passwordEncoder.encode("secret2"))
//                .authorizedGrantTypes("authorization_code")
//                .redirectUris("http://localhost:8005/login")
//                .resourceIds("resource2")
//                .scopes("read", "write")
//                .autoApprove(true);

        // 2：数据库中（默认的表结构与实现）表结构地址：https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
//        clients.jdbc(dataSource).passwordEncoder(passwordEncoder);

        // 3：数据库中（自定义表结构与实现）
        clients.withClientDetails(clientDetailsService);
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security.allowFormAuthenticationForClients()
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()");
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenServices(tokenServices());
    }

    @Bean
    AuthorizationServerTokenServices tokenServices() {
//        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
//        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter(), myTokenEnhancer));
        DefaultTokenServices tokenServices = new DefaultTokenServices();
//        tokenServices.setTokenEnhancer(tokenEnhancerChain);
        // refresh_token的有效时间（秒）
        tokenServices.setRefreshTokenValiditySeconds(6*60*60);
        // token的有效时间（秒）
        tokenServices.setAccessTokenValiditySeconds(24*60*60);
        // 是否支持refresh_token
        tokenServices.setSupportRefreshToken(true);
        // 刷新token的时候，refresh_token是否同步刷新
        tokenServices.setReuseRefreshToken(true);
        tokenServices.setTokenStore(tokenStore());
        tokenServices.setClientDetailsService(clientDetailsService);
        return tokenServices;
    }

    @Bean
    TokenStore tokenStore(){
//        return new InMemoryTokenStore();
//        return new JwtTokenStore(accessTokenConverter());
        return new RedisTokenStore(redisConnectionFactory);
    }

//    @Bean
//    JwtAccessTokenConverter accessTokenConverter(){
//        JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
//        accessTokenConverter.setSigningKey("SigningKey ");
//        return accessTokenConverter;
//    }
}
